<?php
/**
 * @deprecated - 保留此功能，暂时不开发
 *
 * 后台商品规格的管理
 * Author: lyun
 * Date: 2018/3/28
 * Created by Panxsoft.
 */


namespace App\Http\Controllers\Admin\Panx\Product;

use App\Http\Controllers\ApiController;
use App\Http\Requests\Admin\Panx\Product\ProductSpecStoreRequest;
use App\Http\Requests\Admin\Panx\Product\ProductSpecUpdateRequest;
use App\Models\Panx\ProductMod;
use App\Models\Panx\ProductPivotSpecValue;
use App\Models\Panx\Spec;
use App\Models\Panx\SpecValue;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Http\Request;
use Illuminate\Pagination\LengthAwarePaginator;

class ProductSpecController extends ApiController
{
    /**
     * Display a listing of the resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function index()
    {
        /** @var LengthAwarePaginator $specs */
        $specs = Spec::with('productMod','specValues')
            ->latest()
            ->paginate();

        $specs->transform(function(Spec $spec_value){
            $spec_value->values = $spec_value->specValues->pluck('value');

            return $spec_value;
        });

        return $this->response(compact('specs'));
    }

    /**
     * Show the form for creating a new resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function create()
    {
        $product_models = ProductMod::all();

        return $this->response(compact('product_models'));
    }
    
    /**
     * Store a newly created resource in storage.
     *
     * @param  ProductSpecStoreRequest $request
     * @return \Illuminate\Http\Response
     * @throws \Exception
     */
    public function store(ProductSpecStoreRequest $request)
    {
//        $spec_data = $this->assembleSpec($request);
//
//        $stored = Transaction::handle(function() use($request, $spec_data) {
//            $spec = Spec::create($spec_data);
//
//            $this->storeSpecValue($request, $spec);
//
//            return true;
//        });
//
//        return $this->response(compact('stored'));
    }

    /**
     * Display the specified resource.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function show($id)
    {
        //
    }

    /**
     * Show the form for editing the specified resource.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function edit($id)
    {
        //
    }

    /**
     * Update the specified resource in storage.
     *
     * @param  ProductSpecUpdateRequest $request
     * @param  int $id
     * @return \Illuminate\Http\Response
     * @throws \Exception
     */
    public function update(ProductSpecUpdateRequest $request, $id)
    {
//        /** @var Spec $spec */
//        $spec = Spec::find($id);
//            $this->checkItemExist($spec, '商品规格名称');
//
//        $spec_data = $this->assembleSpec($request);
//
//        $updated = Transaction::handle(function() use($request, $spec, $spec_data) {
//            $spec->update($spec_data);
//
//            $this->updateSpecValue($request, $spec);
//
//            return true;
//        }, $throw = true);
//
//        return $this->response(compact('updated'));
    }
    
    /**
     * @deprecated
     *
     * Remove the specified resource from storage.
     *
     * @param  int $id
     *
     * @return void
     * @throws \App\Exceptions\ApiException
     */
    public function destroy($id)
    {
//        /** @var Spec $spec */
//        $spec = Spec::find($id);
//            $this->checkItemExist($spec, '商品规格');
//
//        $spec_value = $spec->specValues;
    }

    /**
     * @param ProductSpecStoreRequest|ProductSpecUpdateRequest|Request $request
     * @return array
     */
    private function assembleSpec(Request $request)
    {
        return [
            'product_mod_id' => $request->product_mod_id,
            'name'             => $request->name,
        ];
    }

    /**
     * @param ProductSpecStoreRequest $request
     * @param Spec $spec
     */
    private function storeSpecValue(ProductSpecStoreRequest $request, Spec $spec)
    {
        $values = $request->values;

        foreach($values as $index => $item) {
            $spec_value = [
                'spec_id' => $spec->id,
                'value'   => $item,
            ];

            SpecValue::create($spec_value);
        }
    }
    
    /**
     * @param ProductSpecUpdateRequest $request
     * @param Spec $spec
     *
     * @return bool
     * @throws \App\Exceptions\ApiException
     */
    private function updateSpecValue(ProductSpecUpdateRequest $request, Spec $spec)
    {
        list(
            $new_spec_values,
            $update_spec_values,
            $delete_spec_val_ids
            ) = $this->normalizeUpdateSpecValueData($request, $spec);

        $this->updateDeleteSpecValues($delete_spec_val_ids);
    
        $this->updateCreateSpecValues($new_spec_values);
    
        $this->updateExistSpecValues($update_spec_values);
    
    
        return true;
    }
    
    
    /**
     * @param ProductSpecUpdateRequest $request
     * @param Spec $spec
     * @return array
     */
    private function normalizeUpdateSpecValueData(ProductSpecUpdateRequest $request,
                                                       Spec $spec)
    {
        $new_spec_values = [];
        $need_update_spec_vals = [];
        $exist_spec_values = $spec->specValues;
        
        foreach ($request->spec_values as $req_spec_val) {
            $req_spec_val_id = $req_spec_val['id'];
            
            if (! $req_spec_val_id) {
                $req_spec_val['spec_id'] = $spec->id;
                array_push($new_spec_values, $req_spec_val);
            } else {
                /** @var SpecValue $exist_spec_value */
                $exist_spec_value = $exist_spec_values->find($req_spec_val_id);
                
                if ($exist_spec_value && $exist_spec_value->value !== $req_spec_val['value']) {
                    array_push($need_update_spec_vals, $req_spec_val);
                }
            }
        }
        
        $req_spec_val_ids = array_column($request->spec_values, 'id');
        $delete_spec_val_ids = $exist_spec_values->whereNotIn('id', $req_spec_val_ids)
            ->pluck('id')->all();
        
        return [
            $new_spec_values,
            $need_update_spec_vals,
            $delete_spec_val_ids
        ];
    }
    
    /**
     * @param array $new_spec_values
     */
    private function updateCreateSpecValues(array $new_spec_values)
    {
        SpecValue::insert($new_spec_values);
    }
    
    /**
     * @param array $update_spec_values
     */
    private function updateExistSpecValues(array $update_spec_values)
    {
        foreach ($update_spec_values as $spec_val) {
            SpecValue::where('id', $spec_val['id'])->update([
                'value' => $spec_val['value'],
            ]);
        }
    }
    
    /**
     * @param array $delete_ids
     *
     * @throws \App\Exceptions\ApiException
     */
    private function updateDeleteSpecValues(array $delete_ids)
    {
        if (! count($delete_ids)) return;
        
        $this->checkCanUpdateDeleteSpecValue($delete_ids);
        
        SpecValue::destroy($delete_ids);
        
        ProductPivotSpecValue::whereIn('spec_value_id', $delete_ids)->delete();
    }
    
    /**
     * @param array $delete_ids
     *
     * @throws \App\Exceptions\ApiException
     */
    private function checkCanUpdateDeleteSpecValue(array $delete_ids): void
    {
        /** @var Collection|ProductPivotSpecValue[] $prod_pvt_spec_vals */
        $prod_pvt_spec_vals = ProductPivotSpecValue::whereIn('spec_value_id', $delete_ids)->get();
    
        if ($prod_pvt_spec_vals->count()) {
            $prod_ids = $prod_pvt_spec_vals->pluck('product_id')->all();
            $prod_ids_str = implode(',', $prod_ids);
            
            $spec_val_ids = $prod_pvt_spec_vals->pluck('spec_value_id')->all();
            $spec_val_ids_str = implode(',', $spec_val_ids);
            
            $this->checkUnless(
                $prod_pvt_spec_vals->count(),
                "产品IDs:{$prod_ids_str}已关联规格值IDs{$spec_val_ids_str}, 无法删除"
            );
        }
    }
}
